package com.pj.gen;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.StrUtil;
import com.fly.jdbc.SqlFlyFactory;
import com.pj.gen.cfg.GenCfg;
import com.pj.gen.cfg.GenCfgManager;
import com.pj.gen.model.DbTable;
import com.pj.gen.read.FlyRead;
import com.pj.gen.read.FlyReadMySql;
import com.pj.gen.read.ReadUtil;
import org.springframework.util.ClassUtils;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 操作工具类
 *
 * @author kong
 */
public class GenUtil {


    public static FlyRead flyRead = new FlyReadMySql();            // 默认的读取实现类


    // 返回读取好的表信息
    public static GenCfg getCodeCfgByReadOk() {
        initTables();
        flyRead.setCodeCfg(GenCfgManager.cfg).readInfo();
        return GenCfgManager.cfg;
    }


    // 开始读取
    public static void doRead() {
        initTables();
        flyRead.setCodeCfg(GenCfgManager.cfg);
        flyRead.readInfo();
    }

    /**
     * 输出java代码 （mybatis-plus版本，经典的三层架构）
     */
    public static void doOutMybatisPlus() {

        for (DbTable t : GenCfgManager.cfg.tableList) {

            /*
             * model.java
             */
            String modelPath = t.getServerIoPathShort() + "model\\" + t.getModelName() + ".java";
            String modelContent = FreeMarkerUtil.getResult("java/Model.ftl", "t", t);
            SUtil.outFile(modelPath, modelContent);
            Print.print(t.getModelName() + " 写入成功：\t\t\t" + modelPath);

            /*
             * modelMagic.java
             */
            String modelMagicPath = t.getServerIoPathShort() + "model\\magic\\" + t.getModelName()+"Magic" + ".java";
            String modelMagicContent = FreeMarkerUtil.getResult("java/ModelMagic.ftl", "t", t);
            SUtil.outFile(modelMagicPath, modelMagicContent);
            Print.print(t.getModelName()+"Magic" + " 写入成功：\t\t\t" + modelMagicPath);

            /*
             * modelExport.java
             */
//            String modelExportPath = t.getServerIoPathShort() + "model\\export\\" + t.getModelName()+"Export" + ".java";
//            String modelExportContent = FreeMarkerUtil.getResult("java/ModelExport.ftl", "t", t);
//            SUtil.outFile(modelExportPath, modelExportContent);
//            Print.print(t.getModelName()+"Export" + " 写入成功：\t\t\t" + modelExportPath);

            /*
             * Dao.java
             */
            String mapperJavaPath = t.getServerIoPathShort() + "dao\\" + t.getMkNameBig() + "Dao.java";
            String mapperJavaContent = FreeMarkerUtil.getResult("java/Dao.ftl", "t", t);
            SUtil.outFile(mapperJavaPath, mapperJavaContent);
            Print.print(t.getModelName() + "Dao.java 写入成功：\t\t" + mapperJavaPath);

            // Mapper.xml
            String mapperXmlPath = t.getServerIoPathShort() + "dao\\" + t.getMkNameBig() + "Mapper.xml";
            String mapperXmlContent = FreeMarkerUtil.getResult("java/Mapper.ftl", "t", t);
            mapperXmlContent = GenCfgManager.cfg.getSqlEncloseRefreshStr(mapperXmlContent);
            SUtil.outFile(mapperXmlPath, mapperXmlContent);
            Print.print(t.getModelName() + "Mapper.xml 写入成功：\t\t" + mapperXmlPath);

            // Service
            String servicePath = t.getServerIoPathShort() + "service\\" + t.getMkNameBig() + "Service.java";
            String serviceContent = FreeMarkerUtil.getResult("java/Service.ftl", "t", t);
            SUtil.outFile(servicePath, serviceContent);
            Print.print(t.getModelName() + "Service 写入成功：\t\t" + servicePath);

            // ServiceImpl
            String serviceImplPath = t.getServerIoPathShort() + "service\\impl\\" + t.getMkNameBig() + "ServiceImpl.java";
            String serviceImplContent = FreeMarkerUtil.getResult("java/ServiceImpl.ftl", "t", t);
            SUtil.outFile(serviceImplPath, serviceImplContent);
            Print.print(t.getModelName() + "ServiceImpl 写入成功：\t\t" + serviceImplPath);

            // Controller
            String controllerPath = t.getServerIoPathShort() + "controller\\" + t.getMkNameBig() + "Controller.java";
            String controllerContent = FreeMarkerUtil.getResult("java/Controller.ftl", "t", t);
            SUtil.outFile(controllerPath, controllerContent);
            Print.print(t.getModelName() + "Controller 写入成功：\t\t" + controllerPath);

            //是否存在统一返回值：AjaxJson，否则补全。
            String ajaxJsonPath = t.getServerIoPathShort() + "utils\\" + "AjaxJson.java";
            File file = new File(ajaxJsonPath);
            if (!file.exists()) {
                String ajaxJsonContent = FreeMarkerUtil.getResult("java/AjaxJson.ftl", "t", t);
                SUtil.outFile(ajaxJsonPath, ajaxJsonContent);
                Print.printR("补全缺失文件AjaxJson：\t\t" + ajaxJsonPath);
            }

            // 多打印一行，模块之间有个间隔
            System.out.println();
        }
    }
    /**
     * 生成Vue3的代码
     */
    public static void doOutAdminVue() {
        //模板文件所在位置
        String path = "freemarker/sp-admin";
        ClassLoader cl = ClassUtils.getDefaultClassLoader();
        URL url = cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path);
        File root = new File(url.getPath());

        for (DbTable t : GenCfgManager.cfg.tableList) {
            // 查
//            String xxxListPath = t.getAdminIoPathShort() + t.getKebabName() + "-list.html";            // 路径
            String xxxListPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\vue3\\") + t.getVarName() + "\\" + t.getVarName() + "-list.vue";            // 路径
            String xxxListContent = FreeMarkerUtil.getResult("v3/xxx-list.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxListPath.substring(xxxListPath.indexOf("src")), xxxListContent);
            Print.print(t.getVarName() + "-list.vue 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxListPath.substring(xxxListPath.indexOf("src")));

            // 增
            String xxxAddPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\vue3\\") + t.getVarName() + "\\" + t.getVarName() + "-add-or-update.vue";            // 路径
            String xxxAddContent = FreeMarkerUtil.getResult("v3/xxx-add.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxAddPath.substring(xxxAddPath.indexOf("src")), xxxAddContent);
            Print.print(t.getVarName() + "-add.vue 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxAddPath.substring(xxxAddPath.indexOf("src")));

            // 详情
            String xxxInfoPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\vue3\\") + t.getVarName() + "\\" + t.getVarName() + "-info.vue";            // 路径
            String xxxInfoContent = FreeMarkerUtil.getResult("v3/xxx-info.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxInfoPath.substring(xxxInfoPath.indexOf("src")), xxxInfoContent);
            Print.print(t.getVarName() + "-info.vue 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxInfoPath.substring(xxxInfoPath.indexOf("src")));

            //CSS
            String xxxcssPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\vue3\\") + t.getVarName() + "\\" + t.getVarName() + ".css";            // 路径
            String xxxcssContent = FreeMarkerUtil.getResult("v3/xxx-css.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxcssPath.substring(xxxcssPath.indexOf("src")), xxxcssContent);
            Print.print(t.getVarName() + ".css 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxcssPath.substring(xxxcssPath.indexOf("src")));

            //Api
            String xxxApiPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\vue3\\") + t.getVarName() + "\\" + t.getVarName() + "-api.js";            // 路径
            String xxxApiContent = FreeMarkerUtil.getResult("v3/xxx-api.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxApiPath.substring(xxxApiPath.indexOf("src")), xxxApiContent);
            Print.print(t.getVarName() + ".api.js 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxApiPath.substring(xxxApiPath.indexOf("src")));
            // 多打印一行，模块之间有个间隔
            System.out.println();
        }
    }
    // 开始生成admin后台管理

    /**
     * @param userTableName 用户表的表名（用来指定token的Key）
     */
    public static void doOutAdminHtml(String userTableName) {
        /**
         * 是否缺失必要的文件，如果缺少则会重新生成。
         */
        //模板文件所在位置
        String path = "freemarker/sp-admin";
        //实际文件所在位置
        String ready = "sp-admin";
        ClassLoader cl = ClassUtils.getDefaultClassLoader();
        URL url = cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path);

        File root = new File(url.getPath());
        List<File> files = listFilesForFolder(root, new ArrayList<File>());
        for (File file : files) {
            //如果相应的位置有没有该文件，则创建
            String replace = file.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin");
            String src = GenCfgManager.cfg.getServerProjectPath() + replace.substring(replace.indexOf("src"));
            File f = new File(src);
            boolean exist = FileUtil.exist(f);
            if (!exist) {
                FileUtil.copy(file, f, false);
                if ("sa.js".equals(f.getName())) {
                    FileReader fileReader = new FileReader(f.getAbsolutePath());
                    String replaceAll = fileReader.readString().replaceAll("satoken", userTableName + "Token");
                    FileWriter fileWriter = new FileWriter(f.getAbsolutePath());
                    fileWriter.write(replaceAll);
                }
                if ("login.html".equals(f.getName())) {
                    FileReader fileReader = new FileReader(f.getAbsolutePath());
                    String replaceAll = fileReader.readString().replaceAll("satoken", userTableName + "Token");
                    FileWriter fileWriter = new FileWriter(f.getAbsolutePath());
                    fileWriter.write(replaceAll);
                }
                Print.printR("补全缺失文件：" + f.getAbsolutePath());
            }
        }


        // 模块
        for (DbTable t : GenCfgManager.cfg.tableList) {
            // 查
//            String xxxListPath = t.getAdminIoPathShort() + t.getKebabName() + "-list.html";            // 路径
            String xxxListPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-view\\" + t.getKebabName() + "\\" + t.getKebabName() + "-list.html";            // 路径
            String xxxListContent = FreeMarkerUtil.getResult("admin/xxx-list.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxListPath.substring(xxxListPath.indexOf("src")), xxxListContent);
            Print.print(t.getKebabName() + "-list.html 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxListPath.substring(xxxListPath.indexOf("src")));

            // 增
            String xxxAddPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-view\\" + t.getKebabName() + "\\" + t.getKebabName() + "-add.html";            // 路径
            String xxxAddContent = FreeMarkerUtil.getResult("admin/xxx-add.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxAddPath.substring(xxxAddPath.indexOf("src")), xxxAddContent);
            Print.print(t.getKebabName() + "-add.html 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxAddPath.substring(xxxAddPath.indexOf("src")));

            // 详情
            String xxxInfoPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-view\\" + t.getKebabName() + "\\" + t.getKebabName() + "-info.html";            // 路径
            String xxxInfoContent = FreeMarkerUtil.getResult("admin/xxx-info.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxInfoPath.substring(xxxInfoPath.indexOf("src")), xxxInfoContent);
            Print.print(t.getKebabName() + "-info.html 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxInfoPath.substring(xxxInfoPath.indexOf("src")));

            // 多打印一行，模块之间有个间隔
            System.out.println();
        }
        // JSX
        for (DbTable t : GenCfgManager.cfg.tableList) {
            // 查
//            String xxxListPath = t.getAdminIoPathShort() + t.getKebabName() + "-list.html";            // 路径
            String xxxListPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-jsx\\" + t.getVarName() + "\\" + t.getVarName() + "-list.jsx";            // 路径
            String xxxListContent = FreeMarkerUtil.getResult("jsx/xxx-list.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxListPath.substring(xxxListPath.indexOf("src")), xxxListContent);
            Print.print(t.getVarName() + "-list.jsx 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxListPath.substring(xxxListPath.indexOf("src")));

            // 增
            String xxxAddPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-jsx\\" + t.getVarName() + "\\" + t.getVarName() + "-add.jsx";            // 路径
            String xxxAddContent = FreeMarkerUtil.getResult("jsx/xxx-add.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxAddPath.substring(xxxAddPath.indexOf("src")), xxxAddContent);
            Print.print(t.getVarName() + "-add.jsx 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxAddPath.substring(xxxAddPath.indexOf("src")));

            // 详情
            String xxxInfoPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-jsx\\" + t.getVarName() + "\\" + t.getVarName() + "-info.jsx";            // 路径
            String xxxInfoContent = FreeMarkerUtil.getResult("jsx/xxx-info.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxInfoPath.substring(xxxInfoPath.indexOf("src")), xxxInfoContent);
            Print.print(t.getVarName() + "-info.jsx 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxInfoPath.substring(xxxInfoPath.indexOf("src")));

            //CSS
            String xxxcssPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-jsx\\" + t.getVarName() + "\\" + t.getVarName() + ".module.css";            // 路径
            String xxxcssContent = FreeMarkerUtil.getResult("jsx/xxx-css.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxcssPath.substring(xxxcssPath.indexOf("src")), xxxcssContent);
            Print.print(t.getVarName() + ".module.css 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxInfoPath.substring(xxxInfoPath.indexOf("src")));

            //Api
            String xxxApiPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-jsx\\" + t.getVarName() + "\\" + t.getVarName() + ".api.js";            // 路径
            String xxxApiContent = FreeMarkerUtil.getResult("jsx/xxx-api.ftl", "t", t);            // 内容
            SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + xxxApiPath.substring(xxxApiPath.indexOf("src")), xxxApiContent);
            Print.print(t.getVarName() + ".api.js 写入成功：\t\t\t" + GenCfgManager.cfg.getServerProjectPath() + xxxInfoPath.substring(xxxInfoPath.indexOf("src")));

            // 多打印一行，模块之间有个间隔
            System.out.println();
        }

        // menu-list.js 菜单列表

        String menuListPath = root.getAbsolutePath().replace("target\\classes\\freemarker\\sp-admin", "src\\main\\resources\\sp-admin") + "\\sa-frame" + File.separator + "menu-list.js";                        // 路径
        String menuListContent = FreeMarkerUtil.getResult("admin/menu-list.ftl", "abc", 123);        // 内容
        SUtil.outFile(GenCfgManager.cfg.getServerProjectPath() + menuListPath.substring(menuListPath.indexOf("src")), menuListContent);
        Print.print("menu-list.js 菜单列表, 写入成功：\t\t" + GenCfgManager.cfg.getServerProjectPath() + menuListPath.substring(menuListPath.indexOf("src")));

    }

    // 开始生成接口文档地址
    public static void doOutApidoc() {
        // 模块
        for (DbTable t : GenCfgManager.cfg.tableList) {
            // 接口文档
            String xxxMdPath = t.getApidocIoPath() + t.getKebabName() + ".md";            // 路径
            String xxxMdContent = FreeMarkerUtil.getResult("apidoc/xxx-md.ftl", "t", t);            // 内容
            SUtil.outFile(xxxMdPath, xxxMdContent);
            System.out.println(t.getKebabName() + ".md 写入成功：\t\t\t" + xxxMdPath);

            // 多打印一行，模块之间有个间隔
//			System.out.println();	
        }

        // sidebar.md 菜单列表
        String sidebarPath = GenCfgManager.cfg.getApidocProjectPath() + "_sidebar.md";                        // 路径
        String sidebarContent = FreeMarkerUtil.getResult("apidoc/sidebar.ftl", "abc", 123);        // 内容
        SUtil.outFile(sidebarPath, sidebarContent);
        System.out.println("_sidebar.js 接口文档目录树, 写入成功：\t\t" + sidebarPath);

    }


    // init 相关依赖
    private static void initTables() {
        // 初始化数据表集合
        if (GenCfgManager.cfg.tableNameList == null || GenCfgManager.cfg.tableNameList.size() == 0) {
            for (String tName : ReadUtil.getTableList(GenCfgManager.cfg.sqlFly.getConnection())) {
                GenCfgManager.cfg.tableNameList.add(tName);
            }
        }
    }

    //获取文件夹下所有文件
    public static List<File> listFilesForFolder(final File folder, List<File> list) {
        for (final File fileEntry : folder.listFiles()) {
            if (fileEntry.isDirectory()) {
                listFilesForFolder(fileEntry, list);
            } else {
                list.add(fileEntry);
            }
        }
        return list;
    }

    //自动建表RBAC经典七张表
    public static void doCreateTable(String user, String role, String menu, String permission) {
        /**
         * 如果没有传入表名，则采用默认表名：sp_user、sp_role、sp_menu、sp_permission
         */
        if (StrUtil.isBlank(user)) {
            user = "sp_user";
        }
        if (StrUtil.isBlank(role)) {
            role = "sp_role";
        }
        if (StrUtil.isBlank(menu)) {
            menu = "sp_menu";
        }
        if (StrUtil.isBlank(permission)) {
            permission = "sp_permission";
        }
        /**
         * 建表10张：用户表、角色表、菜单表、权限表、用户角色表、角色菜单表、角色权限表、登录日志表、API访问日志表、配置表。
         */
        //如果已经存在则跳过TODO
        List<String> tables = new ArrayList<>();
        ;
        List<Map<String, Object>> showTables = SqlFlyFactory.getSqlFly().getMapList("show tables");
        if (showTables.size() != 0) {
            showTables.forEach(x -> tables.addAll(x.values().stream().map(Object::toString).collect(Collectors.toList())));
        }
        Print.print(tables);
        if (!tables.contains(user)) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `" + user + "` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id，--主键、自增',\n" +
                    "  `name` varchar(100) NOT NULL COMMENT 'admin名称',\n" +
                    "  `avatar` varchar(500) DEFAULT NULL COMMENT '头像地址',\n" +
                    "  `password` varchar(100) DEFAULT NULL COMMENT '密码',\n" +
                    "  `pw` varchar(50) DEFAULT NULL COMMENT '明文密码',\n" +
                    "  `phone` varchar(20) DEFAULT NULL COMMENT '手机号',\n" +
                    "  `status` int DEFAULT '1' COMMENT '账号状态(1=正常, 2=禁用)',\n" +
                    "  `create_by_aid` bigint DEFAULT '-1' COMMENT '创建自哪个管理员',\n" +
                    "  `create_time` datetime DEFAULT NULL COMMENT '创建时间',\n" +
                    "  `login_time` datetime DEFAULT NULL COMMENT '上次登陆时间',\n" +
                    "  `login_ip` varchar(50) DEFAULT NULL COMMENT '上次登陆IP',\n" +
                    "  `login_count` int DEFAULT '0' COMMENT '登陆次数',\n" +
                    "  PRIMARY KEY (`id`) USING BTREE,\n" +
                    "  UNIQUE KEY `name` (`name`) USING BTREE\n" +
                    ") ENGINE=InnoDB AUTO_INCREMENT=10004 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='用户表'");
            SqlFlyFactory.getSqlFly().getExecute("" +
                    "INSERT INTO `" + user + "`(`id`, `name`, `avatar`, `password`, `pw`,`phone`, create_time) \n" +
                    "VALUES (1, 'sa', 'https://oss.dev33.cn/sa-plus/in-file/avatar1.jpg', '051C7FF078140C2056843EA6686EEE49', '123456','15267398131', now()),\n" +
                    "(2, 'admin', 'https://oss.dev33.cn/sa-plus/in-file/avatar2.png', '051C7FF078140C2056843EA6686EEE49', '123456','15267398132', now()),\n" +
                    "(3, 'admin2', 'https://oss.dev33.cn/sa-plus/in-file/avatar2.png', '051C7FF078140C2056843EA6686EEE49', '123456', '15267398133', now()); " +
                    "");
        }
        if (!tables.contains(role)) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `" + role + "` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色id，--主键、自增',\n" +
                    "  `name` varchar(20) NOT NULL COMMENT '角色名称, 唯一约束',\n" +
                    "  `info` varchar(200) DEFAULT NULL COMMENT '角色详细描述',\n" +
                    "  `is_lock` int NOT NULL DEFAULT '1' COMMENT '是否锁定(1=是,2=否), 锁定之后不可随意删除, 防止用户误操作',\n" +
                    "  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" +
                    "  PRIMARY KEY (`id`) USING BTREE,\n" +
                    "  UNIQUE KEY `name` (`name`) USING BTREE\n" +
                    ") ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色表';");
            SqlFlyFactory.getSqlFly().getExecute("" +
                    "INSERT INTO `" + role + "`(`id`, `name`, `info`, `is_lock`) VALUES (1, '开发者', '系统开发人员，最高权限', 1),\n" +
                    "(2, '系统管理员', '系统管理员', 2),\n" +
                    "(3, '普通账号', '普通账号', 2),\n" +
                    "(4, '测试角色', '测试角色', 2);" +
                    "");
        }
        if (!tables.contains(menu)) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `" + menu + "` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',\n" +
                    "  `name` varchar(20) CHARACTER SET utf8 NOT NULL COMMENT '菜单名称',\n" +
                    "  `icon` varchar(20) DEFAULT NULL COMMENT '菜单图标',\n" +
                    "  `info` varchar(200) CHARACTER SET utf8 DEFAULT NULL COMMENT '菜单描述',\n" +
                    "  `url` varchar(200) DEFAULT NULL COMMENT '菜单指向地址',\n" +
                    "  `parent_id` bigint DEFAULT NULL COMMENT '所属父菜单id',\n" +
                    "  `is_show` int DEFAULT '1' COMMENT '是否显示',\n" +
                    "  `is_blank` tinyint DEFAULT NULL COMMENT '是否属于外部链接, 如果为true, 则点击菜单时从新窗口打开 ',\n" +
                    "  `click` varchar(255) DEFAULT NULL COMMENT 'function(){}\t\t// 点击菜单执行一个函数 ',\n" +
                    "  `sort` int DEFAULT NULL COMMENT '排序',\n" +
                    "  PRIMARY KEY (`id`) USING BTREE,\n" +
                    "  UNIQUE KEY `name` (`name`) USING BTREE\n" +
                    ") ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='菜单表'");

            SqlFlyFactory.getSqlFly().getExecute("" +
                    "INSERT INTO `" + menu + "`(`id`, `name`, `icon`, `info`, `url`, `parent_id`, `is_show`, `is_blank`, `click`, `sort`) VALUES (1, '权限控制', 'el-icon-unlock', NULL, NULL, NULL, 1, NULL, NULL, NULL),\n" +
                    " (2, '角色列表', NULL, NULL, 'sa-view-sp/sp-role/role-list.html', 1, 1, NULL, NULL, NULL),\n" +
                    " (3, '菜单列表', NULL, NULL, 'sa-view-sp/sp-role/menu-list.html', 1, 1, NULL, NULL, NULL),\n" +
                    " (4, '管理员列表', NULL, NULL, 'sa-view-sp/sp-admin/admin-list.html', 1, 1, NULL, NULL, NULL),\n" +
                    " (5, '管理员添加', NULL, NULL, 'sa-view-sp/sp-admin/admin-add.html', 1, 1, NULL, NULL, NULL),\n" +
                    " (6, '管理员登录日志', NULL, NULL, 'sa-view-sp/sp-admin-login/sp-admin-login-list.html', 1, 1, NULL, NULL, NULL),\n" +
                    " (7, '监控中心', 'el-icon-view', NULL, NULL, NULL, 1, NULL, NULL, NULL),\n" +
                    " (8, 'Redis控制台', NULL, NULL, 'sa-view-sp/sp-console/redis-console.html', 7, 1, NULL, NULL, NULL),\n" +
                    " (9, 'API请求日志', NULL, NULL, 'sa-view-sp/sp-apilog/api-log-list.html', 7, 1, NULL, NULL, NULL),\n" +
                    " (10, 'SQL 监控台', NULL, NULL, 'sa-view-sp/sp-console/sql-console.html', 7, 1, NULL, NULL, NULL),\n" +
                    " (11, '在线表单构建', NULL, NULL, 'https://mrhj.gitee.io/form-generator/', 7, 1, NULL, NULL, NULL),\n" +
                    " (12, '系统配置', 'el-icon-setting', NULL, NULL, NULL, 1, NULL, NULL, NULL),\n" +
                    " (13, '系统对公配置', NULL, NULL, 'sa-view-sp/sp-cfg/app-cfg.html', 12, 1, NULL, NULL, NULL),\n" +
                    " (14, '服务器私有配置', NULL, NULL, 'sa-view-sp/sp-cfg/server-cfg.html', 12, 1, NULL, NULL, NULL);" +
                    "");

        }
        if (!tables.contains(permission)) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `" + permission + "` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',\n" +
                    "  `name` varchar(255) DEFAULT NULL COMMENT '权限名称',\n" +
                    "  `code` varchar(255) DEFAULT NULL COMMENT '权限码',\n" +
                    "  PRIMARY KEY (`id`)\n" +
                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限表';");
            SqlFlyFactory.getSqlFly().getExecute("" +
                    "INSERT INTO `" + permission + "`(`id`,`name`, `code`) VALUES (1,'用户', '" + user.replaceAll("_", "-") + "'),\n" +
                    "(2,'角色', '" + role.replaceAll("_", "-") + "'),\n" +
                    "(3,'菜单', '" + menu.replaceAll("_", "-") + "'),\n" +
                    "(4,'权限', '" + permission.replaceAll("_", "-") + "'),\n" +
                    "(5,'用户角色', '" + (user + "_" + role).replaceAll("_", "-") + "'),\n" +
                    "(6,'角色菜单', '" + (role + "_" + menu).replaceAll("_", "-") + "'),\n" +
                    "(7,'角色权限', '" + (role + "_" + permission).replaceAll("_", "-") + "'),\n" +
                    "(8,'登录日志', '" + (user + "_login").replaceAll("_", "-") + "'),\n" +
                    "(9,'API日志', 'sp-apilog'),\n" +
                    "(10,'配置', 'sp-cfg');" +
                    "");
        }
        if (!tables.contains(user + "_" + role)) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `" + user + "_" + role + "` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',\n" +
                    "  `user_id` bigint DEFAULT NULL COMMENT '用户ID',\n" +
                    "  `role_id` bigint DEFAULT NULL COMMENT '角色ID',\n" +
                    "  PRIMARY KEY (`id`)\n" +
                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色表';");
            SqlFlyFactory.getSqlFly().getExecute("" +
                    "INSERT INTO `" + user + "_" + role + "`(`id`, `user_id`, `role_id`) VALUES (1, 1, 1);\n" +
                    "");
        }
        if (!tables.contains(role + "_" + menu)) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `" + role + "_" + menu + "` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',\n" +
                    "  `role_id` bigint DEFAULT NULL COMMENT '角色ID',\n" +
                    "  `menu_id` bigint DEFAULT NULL COMMENT '菜单ID',\n" +
                    "  PRIMARY KEY (`id`)\n" +
                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色菜单表';");
            SqlFlyFactory.getSqlFly().getExecute("" +
                    "INSERT INTO `" + role + "_" + menu + "`(`id`, `role_id`, `menu_id`) VALUES (1, 1, 1),\n" +
                    "(2, 1, 2),\n" +
                    "(3, 1, 3),\n" +
                    "(4, 1, 4),\n" +
                    "(5, 1, 5),\n" +
                    "(6, 1, 6),\n" +
                    "(7, 1, 7),\n" +
                    "(8, 1, 8),\n" +
                    "(9, 1, 9),\n" +
                    "(10, 1, 10),\n" +
                    "(11, 1, 11),\n" +
                    "(12, 1, 12),\n" +
                    "(13, 1, 13),\n" +
                    "(14, 1, 14);" +
                    "");
        }
        if (!tables.contains(role + "_" + permission)) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `" + role + "_" + permission + "` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',\n" +
                    "  `role_id` bigint DEFAULT NULL COMMENT '角色ID',\n" +
                    "  `permission_id` bigint DEFAULT NULL COMMENT '权限ID',\n" +
                    "  PRIMARY KEY (`id`)\n" +
                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色权限表';");
            SqlFlyFactory.getSqlFly().getExecute("" +
                    "INSERT INTO `" + role + "_" + permission + "`(`id`, `role_id`, `permission_id`) VALUES (1, 1, 1),\n" +
                    "(2, 1, 2),\n" +
                    "(3, 1, 3),\n" +
                    "(4, 1, 4),\n" +
                    "(5, 1, 5),\n" +
                    "(6, 1, 6),\n" +
                    "(7, 1, 7),\n" +
                    "(8, 1, 8),\n" +
                    "(9, 1, 9),\n" +
                    "(10, 1,10);\n" +
                    "");
        }

        if (!tables.contains(user + "_login")) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `" + user + "_login` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id号',\n" +
                    "  `acc_id` bigint(20) NOT NULL COMMENT '管理员账号id',\n" +
                    "  `acc_token` varchar(300) DEFAULT NULL COMMENT '本次登录Token',\n" +
                    "  `login_ip` varchar(50) DEFAULT NULL COMMENT '登陆IP',\n" +
                    "  `address` varchar(127) DEFAULT NULL COMMENT '登录地点',\n" +
                    "  `device` varchar(127) DEFAULT NULL COMMENT '客户端设备标识',\n" +
                    "  `sys` varchar(127) DEFAULT NULL COMMENT '客户端系统标识',\n" +
                    "  `create_time` datetime NOT NULL COMMENT '创建时间',\n" +
                    "  PRIMARY KEY (`id`) USING BTREE\n" +
                    ") ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT \n" +
                    "COMMENT='登录日志表';");
        }

        if (!tables.contains("sp_apilog")) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `sp_apilog` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '请求id',\n" +
                    "  `req_ip` varchar(100) DEFAULT NULL COMMENT '客户端ip',\n" +
                    "  `req_api` varchar(512) DEFAULT NULL COMMENT '请求api',\n" +
                    "  `req_parame` text COMMENT '请求参数',\n" +
                    "  `req_type` varchar(50) DEFAULT NULL COMMENT '请求类型（GET、POST...）',\n" +
                    "  `req_token` varchar(50) DEFAULT NULL COMMENT '请求token',\n" +
                    "  `req_header` text DEFAULT NULL COMMENT '请求header',\n" +
                    "  `res_code` varchar(50) DEFAULT NULL COMMENT '返回-状态码',\n" +
                    "  `res_msg` text COMMENT '返回-信息描述',\n" +
                    "  `res_string` text COMMENT '返回-整个信息字符串形式',\n" +
                    "  `user_id` bigint(20) DEFAULT NULL COMMENT 'user_id',\n" +
                    "  `admin_id` bigint(20) DEFAULT NULL COMMENT 'admin_id',\n" +
                    "  `start_time` datetime(3) DEFAULT NULL COMMENT '请求开始时间',\n" +
                    "  `end_time` datetime(3) DEFAULT NULL COMMENT '请求结束时间',\n" +
                    "  `cost_time` bigint(20) DEFAULT NULL COMMENT '花费时间，单位ms',\n" +
                    "  PRIMARY KEY (`id`) USING BTREE\n" +
                    ") ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='api请求记录表';");
        }

        if (!tables.contains("sp_cfg")) {
            SqlFlyFactory.getSqlFly().getExecute("CREATE TABLE `sp_cfg` (\n" +
                    "  `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id号',\n" +
                    "  `cfg_name` varchar(50) NOT NULL COMMENT '配置名',\n" +
                    "  `cfg_value` text COMMENT '配置值',\n" +
                    "  `remarks` varchar(255) DEFAULT NULL COMMENT '备注',\n" +
                    "  PRIMARY KEY (`id`) USING BTREE,\n" +
                    "  UNIQUE KEY `cfg_name` (`cfg_name`) USING BTREE\n" +
                    ") ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='配置信息表';");
            SqlFlyFactory.getSqlFly().getExecute("" +
                    "INSERT INTO `sp_cfg`(`id`, `cfg_name`, `cfg_value`, `remarks`) VALUES (1, 'app_cfg', '{\"logoUrl\":\"http://sa-admin.dev33.cn/sa-frame/admin-logo.png\",\"appName\":\"Sa-Plus 后台管理\",\"appVersionNo\":\"v1.27.0\",\"appVersionLog\":\"更新于2022-2-21\"}', '应用配置信息，对外公开'),\n" +
                    "(2, 'server_cfg', '{\"reserveInfo\":\"预留信息\",\"userDefaultAvatar\":\"https://oss.dev33.cn/sa-plus/in-file/avatar1.jpg,https://oss.dev33.cn/sa-plus/in-file/avatar2.png\"}', '服务器私有配置');" +
                    "");
        }
        //建完表后生成相关Controller接口和Html。
        GenCfgManager.cfg.removeAllTableName();
        GenCfgManager.cfg.setTableList(new ArrayList<>());
        // 加上SpAdmin的表
        GenCfgManager.cfg.addTableName(user, role, menu, permission, user + "_" + role, role + "_" + menu, role + "_" + permission, user + "_login", "sp_apilog", "sp_cfg");
        GenUtil.doRead();
        GenUtil.doOutMybatisPlus();
        DbTable t = GenCfgManager.cfg.tableList.get(0);

        //加入10张表的名称（首字母大写驼峰）
        t.setUserTableName(StrUtil.upperFirst(StrUtil.toCamelCase(user)));
        t.setRoleTableName(StrUtil.upperFirst(StrUtil.toCamelCase(role)));
        t.setMenuTableName(StrUtil.upperFirst(StrUtil.toCamelCase(menu)));
        t.setPermissionTableName(StrUtil.upperFirst(StrUtil.toCamelCase(permission)));
        t.setUserRoleTableName(StrUtil.upperFirst(StrUtil.toCamelCase(user + "_" + role)));
        t.setRoleMenuTableName(StrUtil.upperFirst(StrUtil.toCamelCase(role + "_" + menu)));
        t.setRolePermissionTableName(StrUtil.upperFirst(StrUtil.toCamelCase(role + "_" + permission)));
        t.setUserLoginTableName(StrUtil.upperFirst(StrUtil.toCamelCase(user + "_login")));
        t.setApiLogTableName(StrUtil.upperFirst(StrUtil.toCamelCase("sp_apilog")));
        t.setCfgTableName(StrUtil.upperFirst(StrUtil.toCamelCase("sp_cfg")));

        //覆盖掉原始用户表Controller
        String userControllerPath = t.getServerIoPathShort() + "controller\\" + t.getUserTableName() + "Controller.java";
        String userControllerContent = FreeMarkerUtil.getResult("java/UserController.ftl", "t", t);
        SUtil.outFile(userControllerPath, userControllerContent);
        Print.print(t.getUserTableName() + "Controller 写入成功(覆盖)：\t\t" + userControllerPath);

        //覆盖掉原始用户登录日志Controller
        String userLoginControllerPath = t.getServerIoPathShort() + "controller\\" + t.getUserLoginTableName() + "Controller.java";
        String userLoginControllerContent = FreeMarkerUtil.getResult("java/UserLoginController.ftl", "t", t);
        SUtil.outFile(userLoginControllerPath, userLoginControllerContent);
        Print.print(t.getUserLoginTableName() + "Controller 写入成功(覆盖)：\t\t" + userLoginControllerPath);

        //覆盖掉原始角色Controller
        String roleControllerPath = t.getServerIoPathShort() + "controller\\" + t.getRoleTableName() + "Controller.java";
        String roleControllerContent = FreeMarkerUtil.getResult("java/RoleController.ftl", "t", t);
        SUtil.outFile(roleControllerPath, roleControllerContent);
        Print.print(t.getRoleTableName() + "Controller 写入成功(覆盖)：\t\t" + roleControllerPath);

        //覆盖掉原始角色权限Controller
        String rolePermissionControllerPath = t.getServerIoPathShort() + "controller\\" + t.getRolePermissionTableName() + "Controller.java";
        String rolePermissionControllerContent = FreeMarkerUtil.getResult("java/RolePermissionController.ftl", "t", t);
        SUtil.outFile(rolePermissionControllerPath, rolePermissionControllerContent);
        Print.print(t.getRolePermissionTableName() + "Controller 写入成功(覆盖)：\t\t" + rolePermissionControllerPath);

        //覆盖掉原始角色菜单Controller
        String roleMenuControllerPath = t.getServerIoPathShort() + "controller\\" + t.getRoleMenuTableName() + "Controller.java";
        String roleMenuControllerContent = FreeMarkerUtil.getResult("java/RoleMenuController.ftl", "t", t);
        SUtil.outFile(roleMenuControllerPath, roleMenuControllerContent);
        Print.print(t.getRoleMenuTableName() + "Controller 写入成功(覆盖)：\t\t" + roleMenuControllerPath);

        //覆盖掉原始角色菜单Controller
        String menuControllerPath = t.getServerIoPathShort() + "controller\\" + t.getMenuTableName() + "Controller.java";
        String menuControllerContent = FreeMarkerUtil.getResult("java/menuController.ftl", "t", t);
        SUtil.outFile(menuControllerPath, menuControllerContent);
        Print.print(t.getMenuTableName() + "Controller 写入成功(覆盖)：\t\t" + menuControllerPath);

        //覆盖掉原始角色菜单Controller
        String permissionControllerPath = t.getServerIoPathShort() + "controller\\" + t.getPermissionTableName() + "Controller.java";
        String permissionControllerContent = FreeMarkerUtil.getResult("java/permissionController.ftl", "t", t);
        SUtil.outFile(permissionControllerPath, permissionControllerContent);
        Print.print(t.getPermissionTableName() + "Controller 写入成功(覆盖)：\t\t" + permissionControllerPath);

        //覆盖掉原始配置表Controller
        String cfgControllerPath = t.getServerIoPathShort() + "controller\\" + t.getCfgTableName() + "Controller.java";
        String cfgControllerContent = FreeMarkerUtil.getResult("java/CfgController.ftl", "t", t);
        SUtil.outFile(cfgControllerPath, cfgControllerContent);
        Print.print(t.getCfgTableName() + "Controller 写入成功(覆盖)：\t\t" + cfgControllerPath);

        //覆盖掉访问日志表Controller
        String apiLogControllerPath = t.getServerIoPathShort() + "controller\\" + t.getApiLogTableName() + "Controller.java";
        String apiLogcontrollerContent = FreeMarkerUtil.getResult("java/ApiLogController.ftl", "t", t);
        SUtil.outFile(apiLogControllerPath, apiLogcontrollerContent);
        Print.print(t.getApiLogTableName() + "Controller 写入成功(覆盖)：\t\t" + apiLogControllerPath);

        //生成缓存Controller
        String cacheControllerPath = t.getServerIoPathShort() + "controller\\" + "Cache" + "Controller.java";
        String cacheControllerContent = FreeMarkerUtil.getResult("java/CacheController.ftl", "t", t);
        SUtil.outFile(cacheControllerPath, cacheControllerContent);
        Print.print("Cache" + "Controller 写入成功(覆盖)：\t\t" + cacheControllerPath);

        //文件上传Controller
        String uploadControllerPath = t.getServerIoPathShort() + "controller\\" + "Upload" + "Controller.java";
        String uploadControllerContent = FreeMarkerUtil.getResult("java/UploadController.ftl", "t", t);
        SUtil.outFile(uploadControllerPath, uploadControllerContent);
        Print.print("Upload" + "Controller 写入成功(覆盖)：\t\t" + uploadControllerPath);


        //写入StpInterface
        String stpInterfacePath = GenCfgManager.cfg.getServerIoPath() + File.separator + "config\\" + "StpInterfaceImpl.java";

        if (!new File(stpInterfacePath).exists()) {
            String stpInterfaceContent = FreeMarkerUtil.getResult("java/StpInterfaceImpl.ftl", "t", t);
            SUtil.outFile(stpInterfacePath, stpInterfaceContent);
            Print.print("补全缺失文件StpUtil：\t\t" + stpInterfacePath);
        }

        //写入StpUtil、以及相关配置。
        String stpUtilPath = GenCfgManager.cfg.getServerIoPath() + File.separator + "config\\" + "Stp" + StrUtil.upperFirst(StrUtil.toCamelCase(user)) + "Util.java";
        File file = new File(stpUtilPath);
        if (!file.exists()) {
            HashMap<String, String> tt = new HashMap<>();
            tt.put("name", StrUtil.upperFirst(StrUtil.toCamelCase(user)));
            tt.put("packagePath", GenCfgManager.cfg.getPackagePath());
            String stpUtilContent = FreeMarkerUtil.getResult("java/StpUtil.ftl", "t", tt);
            SUtil.outFile(stpUtilPath, stpUtilContent);
            Print.print("补全缺失文件StpUtil：\t\t" + stpUtilPath);
        }

        //写入UploadConfig文件上传配置
        String uploadConfigPath = GenCfgManager.cfg.getServerIoPath() + File.separator + "utils\\" + "UploadConfig.java";

        if (!new File(uploadConfigPath).exists()) {
            HashMap<String, String> tt = new HashMap<>();
            tt.put("packagePath", GenCfgManager.cfg.getPackagePath());
            String uploadConfigContent = FreeMarkerUtil.getResult("java/UploadConfig.ftl", "t", tt);
            SUtil.outFile(uploadConfigPath, uploadConfigContent);
            Print.print("补全缺失文件UploadConfig：\t\t" + uploadConfigPath);
        }

        //写入UploadUtil文件上传工具类
        String uploadUtilPath = GenCfgManager.cfg.getServerIoPath() + File.separator + "utils\\" + "UploadUtil.java";

        if (!new File(uploadUtilPath).exists()) {
            HashMap<String, String> tt = new HashMap<>();
            tt.put("packagePath", GenCfgManager.cfg.getPackagePath());
            String uploadUtilContent = FreeMarkerUtil.getResult("java/UploadUtil.ftl", "t", tt);
            SUtil.outFile(uploadUtilPath, uploadUtilContent);
            Print.print("补全缺失文件UploadUtil：\t\t" + uploadUtilPath);
        }

        //写入跨域CorsFilter工具类
        String corsFilterPath = GenCfgManager.cfg.getServerIoPath() + File.separator + "config\\" + "CorsFilter.java";

        if (!new File(corsFilterPath).exists()) {
            HashMap<String, String> tt = new HashMap<>();
            tt.put("packagePath", GenCfgManager.cfg.getPackagePath());
            tt.put("name", StrUtil.upperFirst(StrUtil.toCamelCase(user)));
            String corsFilterContent = FreeMarkerUtil.getResult("java/CorsFilter.ftl", "t", tt);
            SUtil.outFile(corsFilterPath, corsFilterContent);
            Print.print("补全缺失文件CorsFilter：\t\t" + corsFilterPath);
        }
    }
}
